/*
 * @Description:顶点
 */
import { Selection, BaseType } from 'd3-selection';
import { LatLng } from 'leaflet';
import { FeatureInstance, FeatureOption } from '../types';
import Feature from './feature';
import Line from './line';
import Polygon from './polygon';
import { deepClone } from '../util/util';

class Vertex extends Feature {
    relateFeatures: Feature[] = []; // index === 0的关联要素，是第一个建立关联的要素
    constructor(id: string, featureOption: FeatureOption, loc: LatLng, style: any, properties?: any) {
        super(id, featureOption, [[loc]], 'node', properties);
    }

    add(groupSelection: Selection<SVGGElement | BaseType, Feature, BaseType, string>) {
        groupSelection
            .selectChildren('circle.vertex')
            .data(['shadow', 'stroke'])
            .enter()
            .append('circle')
            .call(this.vertexPath.bind(this));

        this.group = groupSelection;
        this.redraw();
        this.addEventListener();
        return this;
    }

    redraw() {
        const latLng = this.latLngs[0][0];
        this.group!.attr('transform', () => this.featureOption.transform.translate(latLng));

        // 只有一个关联要素时，不能是交叉点
        if (this.relateFeatures.length === 1 && this.group.classed('cross')) {
            this.group.classed('cross', false);
        }
        return this;
    }

    vertexPath(selection: Selection<SVGCircleElement, string, BaseType, unknown>) {
        selection
            .attr('class', (klass) => {
                return this.type + ' ' + klass;
            })
            .attr('r', (klass) => {
                return klass === 'shadow' ? 10 : 4;
            });
    }

    changeLatlng(latLng: LatLng, indexs: number[], sequenceNum = 0) {
        const { lat, lng } = this.latLngs[0][0];
        const key = lat + '_' + lng;
        this.featureOption.nodesLayer?.deleteJudgeRepeatItem(key);

        this.latLngs[sequenceNum][indexs[0]] = latLng;
        this.changeAttribute({ className: { 'dashed-vertex': true } });
        this.redraw();
        this.redrawRelateFeature();
    }

    dragEnd() {
        this.changeAttribute({ className: { 'dashed-vertex': false } });
        this.redraw();
        this.relateFeatures.forEach((feature: Feature) => {
            feature.redraw();
        });
        const { lat, lng } = this.latLngs[0][0];
        const key = lat + '_' + lng;
        this.featureOption.nodesLayer!.updateJudgeObject(key, this.id);
    }

    /**
     * 重绘关联要素
     */
    redrawRelateFeature() {
        const latLng = this.latLngs[0][0];
        // 改变关联要素的经纬度
        this.relateFeatures.forEach((feature: Feature) => {
            const { sequence, indexs } = (feature as Line | Polygon).getNodeIndex(this.id);

            if (indexs.length > 0) {
                feature.changeLatlng(latLng, indexs, sequence);
            }
        });
    }

    /**
     * 改变group类名，和圆点的大小
     * @param style className可以是对象也是可以字符串
     */
    changeAttribute(style: { size?: number; className?: { [propName: string]: boolean } | string }) {
        const { size, className } = style;
        if (className) {
            if (typeof className === 'string') {
                // vertex
                this.group.classed(className, true);
            } else {
                // { vertex: false, 'dashed-vertex': true }
                Object.keys(className).forEach((key: string) => {
                    this.group.classed(key, className[key]);
                });
            }
        }
        if (size) {
            this.group.select('.stroke').attr('r', size);
        }
    }

    addRelateFeatures(features: Feature[]) {
        // 允许存在重复的关联要素
        this.relateFeatures = this.relateFeatures.concat(features);
        // features.forEach((item) => {
        //     const exist = this.relateFeatures.some((relate) => relate.id === item.id);
        //     if (!exist) {
        //         this.relateFeatures.push(item);
        //     }
        // });
    }

    /**
     * 删除顶点，去掉关联要素
     */
    remove(): void {
        const vertexId = this.id;

        const { nodesLayer } = this.featureOption;
        if (!nodesLayer) {
            return;
        }

        if (this.relateFeatures && this.relateFeatures.length > 0) {
            // 所有关联要素判断是否需要重绘
            this.relateFeatures.forEach((feature: Feature) => {
                if (!feature.latLngs || feature.latLngs.length === 0) {
                    // 经纬度为空，表示线或者面已经主动删除，顶点的删除是被动删除，则不用进行下边的重绘
                    return;
                }
                if ((feature as Line | Polygon).isMinLatlngNum()) {
                    const { id, type } = feature;
                    this.featureOption.remove(type, id);
                    return;
                }
                const { sequence, indexs } = (feature as Line | Polygon).getNodeIndex(vertexId);

                if (!indexs.length) {
                    return;
                }
                indexs.forEach((index) => {
                    feature.latLngs[sequence].splice(index, 1);
                    (feature as Line | Polygon).relateNodeIds[sequence].splice(index, 1);
                    if (feature.type === 'polygon' && index === 0) {
                        // 面是首尾相连
                        feature.latLngs[sequence][feature.latLngs.length - 1] = feature.latLngs[sequence][0];
                    }
                });

                feature.redraw();
            });

            if (this.latLngs.length > 0) {
                const { lat, lng } = this.latLngs[0][0];
                const key = lat + '_' + lng;
                nodesLayer.deleteJudgeRepeatItem(key);
            }
        }
        this.group.remove();
        this.latLngs = [];
    }

    /**
     * 解绑
     */
    untie() {
        const vertexId = this.id;
        if (!this.relateFeatures || this.relateFeatures.length === 0) {
            return;
        }
        this.relateFeatures.forEach((feature: Feature, i: number) => {
            if (i === 0) {
                // 第一个关联要素，把此顶点样式改成普通顶点，不用重新添加新的顶点
                this.group.classed('cross', false);
                return;
            }
            const { sequence, indexs } = (feature as Line | Polygon).getNodeIndex(vertexId);

            if (!indexs.length) {
                return;
            }
            indexs.forEach((index) => {
                // 添加个普通顶点
                const judgeRepeat = false;
                const show = true;
                const vertexId = this.featureOption.addVertex!(
                    feature.latLngs[sequence][index],
                    [feature],
                    {
                        className: 'vertex',
                        size: 4,
                    },
                    judgeRepeat,
                    show
                );

                // 替换新的顶点id
                (feature as Line | Polygon).relateNodeIds[sequence].splice(index, 1, vertexId);
            });
        });
        // 只保留第一个关联要素
        this.relateFeatures = this.relateFeatures.slice(0, 1);
    }

    instance() {
        const attr: FeatureInstance = {
            ...this.json(),
            getInstanceType: this.getInstanceType.bind(this),
            changeId: this.changeId.bind(this),
            untie: this.untie.bind(this),
            setProperties: this.setProperties.bind(this),
            isEmpty: this.isEmpty.bind(this),
        };
        return deepClone(attr);
    }
}

export default Vertex;
